from collections import OrderedDict
from rest_framework.decorators import api_view
from rest_framework.response import Response
from strategy.models import Strategy
from strategy.metadata import StrategyMetadata
from .serializers import calculate_deduction, trigger_count_serializer

# Create your views here.


@api_view(['GET'])
def overall_rating(request):
    """
    计算综合安全评分
    总安全分值：∑Wi，Wi为第i项策略的权重分
    第i项策略的安全分值Fi：Fi(x,y) = Wi*(1/2*1/(x+1) + 1/2*10/(10+y))，x为触发人数，y为触发次数
    综合安全评分：∑Fi(xi,yi)/∑Wi
    """
    uid2weight = dict(Strategy.objects.filter(category__in=StrategyMetadata.get_categories()).values_list('uid', 'weight'))
    weight_sum = sum(uid2weight.values())
    deduction_sum = sum(calculate_deduction(uid2weight.get(uid, 0), **count)
                        for uid, count in trigger_count_serializer().items())
    data = {'score': round((1 - deduction_sum/weight_sum) * 100) if weight_sum else 0}
    return Response(data)


@api_view(['GET'])
def deduction_details(request):
    """计算安全评分扣分项"""
    uid2stg = {stg.pop('uid'): stg for stg in Strategy.objects.filter(category__in=StrategyMetadata.get_categories()).values('uid', 'name', 'weight', 'level')}
    weight_sum = sum(stg['weight'] for stg in uid2stg.values())
    stg_deductions = []

    levels = OrderedDict()
    for lvl, name in sorted(Strategy.STRATEGY_LEVELS):
        levels[lvl] = {
            'level': name,
            'deduction': 0,
            'weighted_deduction': 0,
            'trigger_count': 0
        }

    level2name = dict(Strategy.STRATEGY_LEVELS)
    for uid, count in trigger_count_serializer().items():
        try:
            stg = uid2stg[uid]
            weight = stg.pop('weight')
            level = stg.pop('level')
            deduction = round(calculate_deduction(weight, **count), 3)
            weighted_deduction = round(deduction / weight_sum * 100, 3)

            stg.update({
                'level': level2name[level],
                'deduction': deduction,
                'weighted_deduction': weighted_deduction,
                **count
            })
            stg_deductions.append(stg)

            levels[level]['deduction'] += deduction
            levels[level]['weighted_deduction'] += weighted_deduction
            levels[level]['trigger_count'] += count['trigger_count']
        except KeyError:
            pass

    for v in levels.values():
        v['deduction'] = round(v['deduction'], 3)
        v['weighted_deduction'] = round(v['weighted_deduction'], 3)
    data = {'levels': levels.values(), 'deductions': stg_deductions}
    return Response(data)
